package com.northpool.operator.common.datasource;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.Method;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.northpool.operator.annotation.InputParam;
import com.northpool.operator.annotation.InputParams;
import com.northpool.operator.annotation.OperatorInfo;
import com.northpool.operator.common.algorithm.OperatorTestBuild;
import com.northpool.operator.common.algorithm.TestParamBuilder;
import com.northpool.operator.common.database.DatabaseUtils;
import com.northpool.operator.common.datasource.bean.DataSourceBean;
import com.northpool.operator.param.ParamTool;
import com.northpool.operator.utils.StpOperatorHelper;
import org.apache.commons.lang3.StringUtils;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.nodes.Tag;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

@OperatorInfo(
        ref = "dataCenterSyncDataSourceOperator",
        version = "1.0.0",
        name = "数据中心数据源信息同步"
)
public class DataCenterSyncDataSourceOperator extends StpOperatorHelper {
    private static DumperOptions options = new DumperOptions();
    private static Yaml yaml;

    static {

        options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK); // 使用块风格
        options.setPrettyFlow(true); // 使输出更易读
        options.setIndentWithIndicator(true);
        options.setIndicatorIndent(2);
        options.setIndent(2); // 设置缩进为2个空格
        options.setAllowUnicode(true); // 允许Unicode字符

        yaml = new Yaml(options);
    }

    @InputParams({
            @InputParam(ref = "serverUrl", name = "平台地址", desc = "http://spatial.mnr.gov.cn", value = "", required = true, testValue = "http://10.21.164.45:8021"),
            @InputParam(ref = "token", name = "用户TOKEN", desc = "用户TOKEN由平台登录用户接口获取", required = true, testValue = "ad9ff990789669c6962d200ccf67a9f5")
    })

    public DataCenterSyncDataSourceOperator() {
        super();
    }

    public static void main(String[] args) throws Exception {
        OperatorTestBuild.execute(DataCenterSyncDataSourceOperator.class,
                TestParamBuilder.aBuilder()
                        .param("serverUrl", "http://10.21.185.1")
                        .param("token", "00f2c93212c9e29dac2f75f0b3d8b7fe")
                        .build());
    }

    @Override
    public void execute(ParamTool params) throws Exception {
        String serverUrl = params.getStr("serverUrl");
        String token = params.getStr("token");
        String url = StrUtil.format("{}/datahub/system/vcatalogservicedatatype/treeloadusertable?node=shujuziyuanmuluROOT&child=true", serverUrl);
        HttpResponse execute = HttpUtil.createRequest(Method.POST, url)
                .header("token", token)
                .setReadTimeout(5000)
                .timeout(5000)
                .execute();
        if (execute.isOk()) {
            String body = execute.body();
            if (StringUtils.isBlank(body)) {
                throw new RuntimeException("返回目录为空");
            }
            Map<String, DataSourceBean> dbMap = new LinkedHashMap<>();
            JSONArray array = JSONArray.parseArray(body);
            this.deepBuildDbMap(array, dbMap);

            // 获取所有数据源参数
            HttpResponse paramGetExecute = HttpUtil.createRequest(Method.GET,  serverUrl + "/stp-jianmu-api/view/external_parameters?type=DB")
                    .header("token", token).execute();
            if (!paramGetExecute.isOk()) {
                throw new RuntimeException("获取当前用户的数据源参数异常: " + paramGetExecute.body());
            }
            JSONArray paramArray = JSONArray.parseArray(paramGetExecute.body());
            Map<String, String> oldParamMap = new HashMap<>();
            for (Object obj : paramArray) {
                JSONObject paramObj = (JSONObject) obj;
                oldParamMap.put(paramObj.getString("ref"), paramObj.getString("value"));
                oldParamMap.put(paramObj.getString("ref"), paramObj.getString("id"));
            }

            for (DataSourceBean dataSource : dbMap.values()) {
                Object jsonObject = JSONObject.toJSON(dataSource);
                String ymlValue = yaml.dumpAs(jsonObject, Tag.MAP, DumperOptions.FlowStyle.BLOCK);
                // 注册或更新全局参数到工具中
                // {"ref":"test","name":"test","type":"STRING","value":"test","label":"默认"}
                // 更新的话是PUT请求
                Method method = Method.POST;
                JSONObject requestBody = new JSONObject();
                requestBody.put("ref", dataSource.getRef());
                requestBody.put("name", dataSource.getName());
                requestBody.put("type", "DB");
                requestBody.put("label", "数据中心");
                requestBody.put("value", ymlValue);
                if (oldParamMap.containsKey(dataSource.getRef())) {
                    method = Method.PUT;
                    requestBody.put("id", oldParamMap.get(dataSource.getRef()));
                    requestBody.remove("ref");
                }
                String paramUrl = serverUrl + "/stp-jianmu-api/external_parameters";
                HttpResponse paramExecute = HttpUtil.createRequest(method, paramUrl)
                        .body(requestBody.toJSONString())
                        .header("token", token).execute();
                if (!paramExecute.isOk()) {
                    throw new RuntimeException("工具中心注册数据源参数失败：" + paramExecute.body());
                }
            }

        } else {
            throw new RuntimeException("数据中心结果异常, 状态码: " + execute.getStatus() + ",响应结果: " + execute.body());
        }
    }

    private void deepBuildDbMap(JSONArray array, Map<String, DataSourceBean> dbMap) {
        for (Object object : array) {
            JSONObject jsonObj = (JSONObject) object;
            JSONObject attributes = jsonObj.getJSONObject("attributes");
            if ("123".equals(attributes.getString("dataType"))) {
                String sourceId = attributes.getString("sourceId");
                DataSourceBean ds = dbMap.get(sourceId);
                if (!dbMap.containsKey(sourceId)) {
                    // 从nacos中获取数据源名称，如果nacos里没有就不记录该条信息
                    String dataSourceName = DatabaseUtils.getDataSourceName(sourceId);
                    if (dataSourceName == null) {
                        this.error("Nacos中不存在数据源ID: {}, 请联系数据中心运维人员同步",  sourceId);
                        continue;
                    }

                    ds = new DataSourceBean();
                    ds.setRef(sourceId);
                    ds.setDescription(dataSourceName);
                    ds.setName(dataSourceName);
                    ds.setDatasets(new ArrayList<>());
                    dbMap.put(sourceId, ds);
                }

                DataSourceBean.DatasetBean dataset = new DataSourceBean.DatasetBean();
                dataset.setRef(attributes.getString("gridName"));
                dataset.setName(attributes.getString("name"));
                ds.getDatasets().add(dataset);
            } else if ("-99".equals(attributes.getString("dataType"))) {
                JSONArray children = jsonObj.getJSONArray("children");
                this.deepBuildDbMap(children, dbMap);
            }
        }
    }
}
